<?php
require_once 'entity/UserSystem.php';
class BaseForm{
	const ENC_APPLICATION = "application/x-www-form-urlencoded";
	const ENC_MULTILPART = "multipart/form-data";
	const ENC_TEXT = "text/plain";
	const METHOD_POST = "post";
	const METHOD_GET = "get";

	const TYPE_TEXTBOX = "textbox";
	const TYPE_DATE = "date";
	const TYPE_CHECKBOX = "checkbox";
	const TYPE_COMBOBOX = "combobox";
	const TYPE_RADIO = "radio";
	const TYPE_IMAGE = "image";
	const TYPE_PASSWORD = "password";
	const FORM_SURFIX = "Form";
	
	const VAL_REQUIRE = "require";
	const VAL_EMAIL = "email";
	const VAL_MAX_LENGHT = "maxleght";
	const VAL_MIN_LENGHT = "minleght";
	const VAL_ONLY_NUMBER = "onlynumber";
	const VAL_ONLY_STRING = "onlystring";
	const VAL_DATE = "date";
	const VAL_HAS_ERROR = "_hasError";
	const VAL_ERROR_MESSAGE = "_errorMessage";
	const VAL_ERROR_DEFAULT = "Dữ liệu bạn nhập chưa đúng, vui long nhập lại";
	
	const MES_SAVE_SUCCESS = "Lưu thành công!";
	
	const COMBO_VAL = "value";
	const COMBO_NAME = "name";

	protected $objectData;
	protected $action;
	protected $enctype;
	protected $method;
	protected $name;
	protected $id;
	protected $class;
	/**
	 * HttpContext.
	 * @var HttpContext
	 */
	protected $context;
	/**
	 * Entity.
	 * @var BaseEntity.
	 */
	protected $entity;
	protected $tableName;

	public $baseLabelMap = array(
	BaseEntity::CREATEBY => 'Tạo bởi',
	BaseEntity::CREATETIME => 'Tạo lúc',
	BaseEntity::LASTUPDATEBY => 'Cập nhật lần cuối bởi',
	BaseEntity::LASTUPDATETIME => 'Cập nhật lần cuối lúc',
	BaseEntity::ROWVERSION => 'Số lần cập nhật',
	BaseEntity::STATUS => 'Trạng thái'
	);

	public $labelMap = array();
	public $leftcols = array();
	public $rightcols = array();
	public $defaultLefts = array(
		BaseEntity::CREATEBY =>BaseEntity::CREATENAME,
		BaseEntity::CREATETIME =>BaseEntity::CREATETIME,
		BaseEntity::ROWVERSION =>BaseEntity::ROWVERSION
	);
	public $defaultRights = array(
		BaseEntity::LASTUPDATEBY =>BaseEntity::LASTUPDATENAME, 
		BaseEntity::LASTUPDATETIME =>BaseEntity::LASTUPDATETIME
	);
	public $gender = array(
		array(BaseForm::COMBO_VAL => 0,BaseForm::COMBO_NAME =>"Nữ"),
		array(BaseForm::COMBO_VAL => 1,BaseForm::COMBO_NAME =>"Nam")
	);
	public $valMessage = array(
		BaseForm::VAL_REQUIRE => "Bạn phải nhập {0}.",
		BaseForm::VAL_EMAIL => "{0} chưa đúng định dạng email.",
		BaseForm::VAL_ONLY_NUMBER => "{0} chỉ được nhập số.",
		BaseForm::VAL_ONLY_STRING => "{0} Chỉ được nhập chuỗi.",
		BaseForm::VAL_DATE => "{0} chưa đúng định dạng ngày tháng."
	);
	public function __construct($data = null, $id = "",
		$name = "", $class = "",
		$action = "", $enctype = "",
		$method = "", $context = null){
		$this->objectData = $data;
		$this->action = $action;
		$this->enctype = $enctype;
		$this->method = $method;
		$this->name = $name;
		$this->id = $id;
		$this->class = $class;
		$this->context = $context;
		$this->init();
		$this->initStatus();
	}

	public function init(){
	
	}
	public function initStatus(){
		$sql = 'select * from status';
		$db = DBHelper::getInstance();
		$this->status = $db->fetchAll($sql);
	}
	public function setData($data){
		$this->objectData = $data;
	}
	public function setAction($action){
		$this->action = $action;
	}
	public function setEnctype($enctype){
		$this->enctype = $enctype;
	}
	public function setMethod($method){
		$this->method = $method;
	}
	public function setName($name){
		$this->name = $name;
	}
	public function setTableName($tablename){
		$this->tableName = $tablename;
		$this->entity = EntityFactory::instance($tablename);
	}
	public function getEntity(){
		return $this->entity;
	}
	public function setID($id){
		$this->id = $id;
	}
	public function setClass($class){
		$this->class = $class;
	}
	public function setContext($context){
		$this->context = $context;
	}

	public function render(){
		echo '<form class="form edit '.$this->class.'" id="'.$this->id.'" name="'.$this->name.'" enctype="'.$this->enctype.'" action="'.$this->action.'" method="'.$this->method.'">';
		echo '<div class="ctr-frame">';
		echo '<div class="left">';
		$i = 0;
		$i = $this->renderID($i);
		foreach ($this->leftcols as $key=> $value) {
			$class = "r" . ($i%2);
			if(isset($value[5]))
				$class .= $this->getRequireClass($value[5]);
			$this->renderLbCtr($key, $value,$class);
			$i++;
		}
		$i = $this->renderDefaultLeft($i);
		echo '</div>';
		/////////////////////////////////////////////////////
		echo '<div class="right">';
		$j = 0;
		foreach ($this->rightcols as $key=> $value) {
			$class = "r" . ($j%2);
			if(isset($value[5]))
				$class .= $this->getRequireClass($value[5]);
			$this->renderLbCtr($key, $value,$class);
			$j++;
		}
		$j = $this->renderDefaultRight($j);
		echo '</div>';
		echo '</div>';
		echo '<div class="bt-frame">';
		$this->resetButton();
		$this->submitButton();
		echo '</div>';
		echo '</form>';
	}
	private function getRequireClass(array $data){
		$str = "";		
		foreach ($data as $value) {
			$str .= " ".$value;
		}
		return $str;
	}
	public function renderID($i){
		if(isset($this->objectData)){
			foreach ($this->entity->ID() as $value) {
				$class = "r" . ($i%2);
				$val = isset($this->objectData[$value])?$this->objectData[$value]:"";
				echo '<div class="elemt c1 '.$class.' '.BaseForm::VAL_REQUIRE.'">';
				echo '<div class="lb">'.$this->labelMap[$value].':</div>';
				echo '<div class="lb "><input type="hidden" name="'.$this->tableName.'_'.$value.'" value="'.$val.'">'.$val.'</div>';
				echo '</div>';
				$i++;
			}
		}
		else{
			foreach ($this->entity->getNextID() as $key=>$value) {
				$class = "r" . ($i%2);
				echo '<div class="elemt c1 '.$class.' '.BaseForm::VAL_REQUIRE.'">';
				echo '<div class="lb">'.$this->labelMap[$key].':</div>';
				echo '<div class="lb "><input type="hidden" name="'.$this->tableName.'_'.$key.'" value="'.$value.'">'.$value.'</div>';
				echo '</div>';
				$i++;
			}
		}
		return $i;
	}
	public function renderDefaultRight($i){
		$auth = Auth::getSession();
		$updateby = $auth[UserSystem::ID];
		$updatename = $auth[UserSystem::NAME];
		$updatetime = date("Y-m-d H:i:s");
		$updatetime1 = date("Y-m-d H:i:s");  
		$status = BaseEntity::DEFAULT_STATUS;
		if(isset($this->objectData)){
			$updatename = $this->objectData[BaseEntity::LASTUPDATENAME];
			$updatetime1 = $this->objectData[BaseEntity::LASTUPDATETIME];
			$status = $this->objectData[BaseEntity::STATUS];
		}
		$class = "r" . ($i%2);
		echo '<div class="elemt c1 '.$class.'">';
		echo '<div class="lb">'.$this->baseLabelMap[BaseEntity::LASTUPDATEBY].':</div>';
		echo '<div class="lb ">';
			echo $updatename;
			echo '<input type="hidden" name="'.$this->tableName.'_'.BaseEntity::LASTUPDATENAME.'" value="'.$updatename.'"/>';
			echo '<input type="hidden" name="'.$this->tableName.'_'.BaseEntity::LASTUPDATEBY.'" value="'.$updateby.'"/>';
		echo '</div>';
		echo '</div>';
		$i++;
		$class = "r" . ($i%2);
		echo '<div class="elemt c1 '.$class.'">';
		echo '<div class="lb">'.$this->baseLabelMap[BaseEntity::LASTUPDATETIME].':</div>';
		echo '<div class="lb ">';
			echo $updatetime1;
			echo '<input type="hidden" name="'.$this->tableName.'_'.BaseEntity::LASTUPDATETIME.'" value="'.$updatetime.'"/>';
		echo '</div>';
		echo '</div>';
		$i++;
		$class = "r" . ($i%2);
		echo '<div class="elemt c1 '.$class.'">';
		echo '<div class="lb">'.$this->baseLabelMap[BaseEntity::STATUS].':</div>';
		echo '<div class="ctr ">';
		echo '<select name="'.$this->tableName.'_'.BaseEntity::STATUS.'">';	
		foreach ($this->status as $value) {
			$selected = '';
			if($status == $value['id'])
				$selected = ' selected="selected"'; 
			echo '<option '.$selected.' value="'.$value['id'].'">'.$value['name'].'</option>';
		}
		echo '</select>';
		echo '</div>';
		echo '</div>';
		$i++;
		return $i;
	}
	public function renderDefaultLeft($i){
		$auth = Auth::getSession();
		$createby = $auth[UserSystem::ID];
		$createname = $auth[UserSystem::NAME];
		$createtime = date("Y-m-d H:i:s");
		$rowversion = 0;
		if(isset($this->objectData)){
			$createby = $this->objectData[BaseEntity::CREATEBY];
			$createname = $this->objectData[BaseEntity::CREATENAME];
			$createtime = $this->objectData[BaseEntity::CREATETIME];
			$rowversion = $this->objectData[BaseEntity::ROWVERSION];
		}
		$class = "r" . ($i%2);
		echo '<div class="elemt c1 '.$class.'">';
		echo '<div class="lb">'.$this->baseLabelMap[BaseEntity::CREATEBY].':</div>';
		echo '<div class="lb ">';
			echo $createname;
			echo '<input type="hidden" name="'.$this->tableName.'_'.BaseEntity::CREATENAME.'" value="'.$createname.'"/>';
			echo '<input type="hidden" name="'.$this->tableName.'_'.BaseEntity::CREATEBY.'" value="'.$createby.'"/>';
		echo '</div>';
		echo '</div>';
		$i++;
		$class = "r" . ($i%2);
		echo '<div class="elemt c1 '.$class.'">';
		echo '<div class="lb">'.$this->baseLabelMap[BaseEntity::CREATETIME].':</div>';
		echo '<div class="lb ">';
			echo $createtime;
			echo '<input type="hidden" name="'.$this->tableName.'_'.BaseEntity::CREATETIME.'" value="'.$createtime.'"/>';
		echo '</div>';
		echo '</div>';
		$i++;
		$class = "r" . ($i%2);
		echo '<div class="elemt c1 '.$class.'">';
		echo '<div class="lb">'.$this->baseLabelMap[BaseEntity::ROWVERSION].':</div>';
		echo '<div class="lb ">';
			echo $rowversion;
			echo '<input type="hidden" name="'.$this->tableName.'_'.BaseEntity::ROWVERSION.'" value="'.($rowversion + 1).'"/>';
		echo '</div>';
		echo '</div>';
		$i++;
		return $i;
	}
	public function renderStatus($class){
		echo '<div class="elemt c1 '.$class.'">';
		echo '<div class="lb">'.$this->baseLabelMap[BaseEntity::STATUS].':</div>';
		echo '<div class="ctr "><select name="'.BaseEntity::STATUS.'">';
		foreach ($this->status as $value) {
			$selected = '';
			if($this->objectData[BaseEntity::STATUS] == $value['id'])
				$selected = ' selected="selected"'; 
			echo '<option '.$selected.' value="'.$value['id'].'">'.$value['name'].'</option>';
		}
		echo '</select></div>';
		echo '</div>';
	}
	public function renderLbCtr($name,$data,$class){
		switch ($data[0]) {
			case BaseForm::TYPE_TEXTBOX:
				$this->renderTextBox($name, $data,$class);
				break;
			case BaseForm::TYPE_CHECKBOX:
				$this->renderCheckBox($name, $data,$class);
				break;
			case BaseForm::TYPE_COMBOBOX:
				$this->renderComboBox($name, $data,$class);
				break;
			case BaseForm::TYPE_RADIO:
				$this->renderRadio($name, $data,$class);
				break;
			case BaseForm::TYPE_DATE:
				$this->renderDate($name, $data,$class);
				break;
			case BaseForm::TYPE_IMAGE:
				$this->renderImage($name, $data,$class);
				break;
			case BaseForm::TYPE_PASSWORD:
				$this->renderPassword($name, $data,$class);
				break;
			default:
				$this->renderDefault($name, $data, $class);
				break;
		}
	}

	public function renderTextBox($name,$data,$class){
		$place = isset($data[4])? $data[4]:"";
		$value = isset($this->objectData[$name])?$this->objectData[$name]:"";
		$disabled = "";
		if($data[3])$disabled = 'readonly="readonly"';
		echo '<div class="elemt c'.$data[1].' '.$class.'">';
		echo '<div class="lb">'.$this->labelMap[$name].':</div>';
		echo '<div class="ctr "><input type="text" name="'.$this->tableName.'_'.$name.'" placeholder="'.$place.'" value="'.$value.'" '.$disabled.'></div>';
		echo '</div>';
	}
	public function renderPassword($name,$data,$class){
		$place = isset($data[4])? $data[4]:"";
		$value = isset($this->objectData[$name])?$this->objectData[$name]:"";
		$disabled = "";
		if($data[3])$disabled = 'disabled="disabled"';
		echo '<div class="elemt c'.$data[1].' '.$class.'">';
		echo '<div class="lb">'.$this->labelMap[$name].':</div>';
		echo '<div class="ctr "><input type="password" name="'.$this->tableName.'_'.$name.'" placeholder="'.$place.'" value="" '.$disabled.'></div>';
		echo '</div>';
	}
	public function renderComboBox($name,$data,$class){
		$fvalue = isset($this->objectData[$name])?$this->objectData[$name]:"";
		echo '<div class="elemt c'.$data[1].' '.$class.'">';
		echo '<div class="lb">'.$this->labelMap[$name].':</div>';
		echo '<div class="ctr ">';
		echo '<select name="'.$this->tableName.'_'.$name.'">';
		foreach ($data[2] as $value) {
			$selected = "";
			if($fvalue == $value[BaseForm::COMBO_VAL]) $selected = ' selected="selected"';
			echo '<option value="'.$value[BaseForm::COMBO_VAL].'" '.$selected.'>'.$value[BaseForm::COMBO_NAME].'</option>';
		}
		echo '</select>';
		echo '</div>';
		echo '</div>';
	}
	public function renderCheckBox($name,$data,$class){
		echo '<div class="elemt c'.$data[1].' '.$class.'">';
		echo '<div class="lb">'.$this->labelMap[$name].':</div>';
		echo '<div class="ctr "></div>';
		echo '</div>';
	}
	public function renderRadio($name,$data,$class){
		echo '<div class="elemt c'.$data[1].' '.$class.'">';
		echo '<div class="lb">'.$this->labelMap[$name].':</div>';
		echo '<div class="ctr ">';
			
		echo '</div>';
		echo '</div>';
	}
	public function renderDate($name,$data,$class){
		$place = isset($data[4])? $data[4]:"";
		$value = isset($this->objectData[$name])?$this->objectData[$name]:"";
		echo '<div class="elemt c'.$data[1].' '.$class.'">';
		echo '<div class="lb">'.$this->labelMap[$name].':</div>';
		echo '<div class="ctr "><input type="text" name="'.$this->tableName.'_'.$name.'" placeholder="'.$place.'" value="'.$value.'"></div>';
		echo '</div>';
	}
	public function renderImage($name,$data,$class){
		$value = isset($this->objectData[$name])?$this->objectData[$name]:"";
		echo '<div class="elemt c'.$data[1].' '.$class.'">';
		echo '<div class="lb">'.$this->labelMap[$name].':</div>';
		echo '<div class="ctr ">';
		if(isset($this->objectData[$name]) && $this->objectData[$name] != ""){
			echo '<image class="form-img" src="'.$this->getImageFolder() . $value . '">';
		}
		echo '<input type="hidden" name="'.$this->tableName.'_'.$name.'" value="'.$value.'">';
		echo '<input type="file" name="File_'.$name.'">';
		echo '</div>';
		echo '</div>';
	}
	public function renderDefault($key,$name,$class){
		$valueName = isset($this->objectData[$key])?$this->objectData[$key]:"";
		$value = isset($this->objectData[$name])?$this->objectData[$name]:"";
		echo '<div class="elemt c1 '.$class.'">';
		echo '<div class="lb">'.$this->baseLabelMap[$key].':</div>';
		echo '<div class="ctr ">'.$valueName;
		echo '<input type="hidden" name="'.$this->tableName.'_'.$name.'" value="'.$value.'">';
		echo '</div>';
		echo '</div>';
	}
	public function getObjectData(){
		return $this->objectData;
	}
	public function resetButton(){
		echo '<button class="bt btnew" type="reset" name="btNew">New</button>';
	}
	public function submitButton(){
		echo '<button class="bt btsave" type="submit" name="btSave" value="Save">Save</button>';
	}
	public function getImageFolder(){
		return $this->context->getBaseUrl() . IMAGE_URL . strtolower($this->tableName) . SLASH;
	}
	public function validate1($data){
		foreach ($this->leftcols as $key=>$value) {
			if(isset($value[5])){
				foreach ($value[5] as $validate) {
					$data = $this->validateElement1($data,$key, $validate);
					if(isset($data[BaseForm::VAL_HAS_ERROR]) && $data[BaseForm::VAL_HAS_ERROR] == true)
						return $data;
				}
			}
		}
		foreach ($this->rightcols as $key=>$value) {
			if(isset($value[5])){
				foreach ($value[5] as $validate) {
					$data = $this->validateElement1($data,$key, $validate);
					if(isset($data[BaseForm::VAL_HAS_ERROR]) && $data[BaseForm::VAL_HAS_ERROR] == true)
						return $data;
				}
			}
		}
		return $data;
	}
	private function validateElement1($data,$key,$type){
		switch ($type) {
			case BaseForm::VAL_REQUIRE:
			return $this->checkRequire1($data, $key);
			break;
			
			default:
				;
			break;
		}
	}
	private function checkRequire1($data,$key){
		if(!isset($data[":".$key]) || $data[":".$key]==""){
			$data[BaseForm::VAL_HAS_ERROR] = true;
			$data[BaseForm::VAL_ERROR_MESSAGE] = $this->getMessageStr(BaseForm::VAL_REQUIRE, array($key));
		}
		return $data;
	}
	private function getMessageStr($msgKey,array $data){
		$message = $this->valMessage[$msgKey];
		$i = 0;
		foreach ($data as $value) {
			$key = '{'.$i.'}';
			$str = $this->labelMap[$value];
			$message = str_replace($key, $str, $message);
			$i++;
		}
		return $message;
	}
}